home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIPNET Aralık 1997.iso / linux / redhat / misc / src / install / lilo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-11  |  14.1 KB  |  568 lines

  1. #include <alloca.h>
  2. #include <newt.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <sys/stat.h>
  7. #include <unistd.h>
  8.  
  9. #include "devices.h"
  10. #include "install.h"
  11. #include "lilo.h"
  12. #include "log.h"
  13. #include "run.h"
  14. #include "windows.h"
  15.  
  16. #ifdef __i386__
  17. static char * kernelPath = "/boot/vmlinuz";
  18. #elif __sparc__
  19. static char * kernelPath = "/boot/vmlinux.gz";
  20. #else
  21. #error unsupported architecture
  22. #endif
  23.  
  24. static int mkinitrd(char * kernelVersion) {
  25.     char * argv[] = { "/sbin/mkinitrd", "/boot/initrd", "--ifneeded", 
  26.             kernelVersion, NULL };
  27.     int rc;
  28.     static alreadyHappened = 0;
  29.  
  30.     #ifdef __sparc__
  31.     return 0;
  32.     #endif
  33.  
  34.     if (alreadyHappened) return 0;
  35.  
  36.     if (!access("/mnt/boot/initrd", X_OK)) {
  37.     logMessage("/mnt/boot/initrd exists -- moving to "
  38.             "/mnt/boot/initrd.orig");
  39.     rename("/mnt/boot/initrd", "/mnt/boot/initrd.orig");
  40.     }
  41.  
  42.     if (loadModule("loop", DRIVER_OTHER, DRIVER_MINOR_NONE, NULL)) 
  43.     return INST_ERROR;
  44.  
  45.     winStatus(32, 3, "LILO", "Creating initial ramdisk...");
  46.     rc = runProgramRoot(RUN_LOG, "/mnt", "/sbin/mkinitrd", argv);
  47.     newtPopWindow();
  48.  
  49.     removeModule("loop");
  50.  
  51.     if (rc) {
  52.     unlink("/mnt/boot/initrd");
  53.     } else {
  54.     alreadyHappened = 1;
  55.     }
  56.  
  57.     return rc;
  58. }
  59.  
  60. #define SKIP_LILO 1000
  61.  
  62. #if defined(__i386__)
  63. static int liloWhere(char * hdName, char * bootDevice, char ** where) {
  64.     newtComponent form, okay, listbox, cancel, answer, skip;
  65.     char * format = "/dev/%-7s    %s";
  66.     char buf[200];
  67.     void * which;
  68.  
  69.     newtOpenWindow(12, 6, 55, 11, "Lilo Installation");
  70.  
  71.     form = newtForm(NULL, NULL, 0);
  72.     newtFormAddComponent(form, 
  73.         newtLabel(1, 1, "Where do you want to install "
  74.                 "the bootloader?"));
  75.  
  76.     listbox = newtListbox(2, 3, 3, NEWT_LISTBOX_RETURNEXIT);
  77.     sprintf(buf, format, hdName, 
  78.             "Master Boot Record");
  79.     newtListboxAddEntry(listbox, buf, (void *) 1);
  80.     sprintf(buf, format, bootDevice, 
  81.             "First sector of boot partition");
  82.     newtListboxAddEntry(listbox, buf, (void *) 2);
  83.     sprintf(buf, format, "fd0", 
  84.             "First sector of a floppy disk");
  85.     newtListboxAddEntry(listbox, buf, (void *) 3);
  86.  
  87.     okay = newtButton(6, 7, "Ok");
  88.     skip = newtButton(22, 7, "Skip");
  89.     cancel = newtButton(38, 7, "Cancel");
  90.     newtFormAddComponents(form, listbox, okay, skip, cancel, NULL);
  91.  
  92.     answer = newtRunForm(form);
  93.  
  94.     which = newtListboxGetCurrent(listbox);
  95.     
  96.     newtFormDestroy(form);
  97.     newtPopWindow();
  98.  
  99.     if (answer == cancel) return INST_CANCEL;
  100.     if (answer == skip) return SKIP_LILO;
  101.  
  102.     switch ((int) which) {
  103.       case 1:         *where = hdName; break;
  104.       case 2:         *where = bootDevice; break;
  105.       case 3:         *where = "fd0"; break;
  106.     }
  107.  
  108.     return 0;
  109. }
  110. #elif defined(__sparc__)
  111. static int liloWhere(char * hdName, char * bootDevice, char ** where) {
  112.     newtComponent text, yes, no, cancel, f, answer;
  113.     int rc;
  114.  
  115.     newtOpenWindow(18, 6, 42, 10, "SILO Installation");
  116.  
  117.     text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP);
  118.     newtTextboxSetText(text,
  119.         "Would you like to install or configure the SILO bootloader on "
  120.         "your system?");
  121.  
  122.     yes = newtButton(3, 6, " Yes ");
  123.     no = newtButton(16, 6, "  No  ");
  124.     cancel = newtButton(29, 6, "Cancel");
  125.  
  126.     f = newtForm(NULL, NULL, 0);
  127.     newtFormAddComponents(f, text, yes, no, cancel, NULL);
  128.  
  129.     answer = newtRunForm(f);
  130.     if (answer == f) 
  131.     answer = newtFormGetCurrent(f);
  132.  
  133.     newtPopWindow();
  134.     newtFormDestroy(f);
  135.  
  136.     if (answer == yes) {
  137.         *where = bootDevice; 
  138.     rc = 0;
  139.     } else if (answer == cancel) {
  140.     rc = INST_CANCEL;
  141.     return INST_CANCEL;
  142.     } else {
  143.     rc = SKIP_LILO;
  144.     }
  145.  
  146.     return rc;
  147. }
  148. #endif
  149.  
  150. static void editBootLabel(struct partition * item) {
  151.     newtComponent form, entry, okay, cancel, clear, answer;
  152.     char buf[50];
  153.     char * entryValue;
  154.  
  155.     newtOpenWindow(10, 7, 50, 10, "Edit Boot Label");
  156.  
  157.     form = newtForm(NULL, NULL, 0);
  158.  
  159.     strcpy(buf,"Device      : /dev/");
  160.     strcat(buf, item->device);
  161.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  162.     newtFormAddComponent(form, newtLabel(1, 3, "Boot label :"));
  163.  
  164.     entry = newtEntry(17, 3, item->bootLabel, 20, &entryValue, 
  165.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  166.  
  167.     okay = newtButton(5, 6, "Ok");
  168.     clear = newtButton(20, 6, "Clear");
  169.     cancel = newtButton(35, 6, "Cancel");
  170.  
  171.     newtFormAddComponents(form, entry, okay, clear, cancel, NULL);
  172.  
  173.     do {
  174.     answer = newtRunForm(form);
  175.  
  176.     if (answer == clear)
  177.         newtEntrySet(entry, "", 1);
  178.     } while (answer == clear);
  179.  
  180.     if (answer != cancel) {
  181.     if (item->bootLabel) free(item->bootLabel);
  182.  
  183.     if (strlen(entryValue))
  184.         item->bootLabel = strdup(entryValue);
  185.     else
  186.         item->bootLabel = NULL;
  187.     }
  188.  
  189.     newtPopWindow();
  190. }        
  191.  
  192. static int doinstallLilo(char * prefix, char * dev, char * rootdev,
  193.              struct partitionTable table,
  194.              char * append, char * kernelVersion, 
  195.              char * hdname, int linear) {
  196.     char filename[100];
  197.     FILE * f;
  198.     char * argv[] = { "/mnt/sbin/lilo", NULL };
  199.     int i;
  200.     int rc;
  201.     struct stat sb;
  202.     int useInitrd = 0;
  203.     struct partition * root = NULL;
  204.  
  205.     if (mkinitrd(kernelVersion))
  206.     return INST_ERROR;
  207.  
  208.     if (!stat("/mnt/boot/initrd", &sb))
  209.     useInitrd = 1;
  210.  
  211.     #ifdef __sparc__
  212.     sprintf(filename, "%s/silo.conf", prefix);
  213.     #else
  214.     sprintf(filename, "%s/lilo.conf", prefix);
  215.     #endif
  216.  
  217.     /* why not? */
  218.     rename("/mnt/etc/lilo.conf", "/mnt/etc/lilo.conf.orig");
  219.     rename("/mnt/etc/silo.conf", "/mnt/etc/silo.conf.orig");
  220.     
  221.     f = fopen(filename, "w");
  222.     if (!f) {
  223.     errorWindow("cannot create [ls]ilo config file: %s");
  224.     return INST_ERROR;
  225.     }
  226.  
  227.     logMessage("writing [sl]ilo config to %s", filename);
  228.  
  229.     for (i = 0; i < table.count; i++) {
  230.     if (table.parts[i].bootLabel && 
  231.         table.parts[i].type == PART_EXT2) {
  232.         root = table.parts + i;
  233.     }
  234.     }
  235.  
  236.     if (!root) {
  237.     errorWindow("No ext2 partition is bootable");
  238.     return INST_ERROR;
  239.     }
  240.  
  241.     #ifdef __i386__
  242.     fprintf(f, "boot=/dev/%s\n", dev);
  243.     fprintf(f, "map=/boot/map\n");
  244.     fprintf(f, "install=/boot/boot.b\n");
  245.     fprintf(f, "prompt\n");
  246.     if (linear) fprintf(f, "linear\n");
  247.     fprintf(f, "timeout=50\n");
  248.     #elif __sparc__
  249.     fprintf(f, "timeout=50\n");
  250.     fprintf(f, "partition=%s\n", root->device + 3);
  251.     fprintf(f, "root=/dev/%s\n", root->device);
  252.     #else
  253.     #error "unsupported architecture";
  254.     #endif
  255.  
  256.     for (i = 0; i < table.count; i++) {
  257.     if (table.parts[i].bootLabel) {
  258.         if (table.parts[i].type == PART_EXT2) {
  259.         fprintf(f, "image=%s\n", kernelPath);
  260.         fprintf(f, "\tlabel=%s\n", table.parts[i].bootLabel);
  261.         
  262.         /* we can setup a /boot on the fresh system if we need to */
  263.         if (!strcmp(table.parts[i].device, dev))
  264.             fprintf(f, "\troot=/dev/%s\n", rootdev);
  265.         else
  266.             fprintf(f, "\troot=/dev/%s\n", table.parts[i].device);
  267.         if (useInitrd)
  268.             fprintf(f, "\tinitrd=/boot/initrd\n");
  269.         if (append) fprintf(f, "\tappend=\"%s\"\n", append);
  270.         fprintf(f, "\tread-only\n");
  271.       #ifdef __i386__
  272.         } else {
  273.         fprintf(f, "other=/dev/%s\n", table.parts[i].device);
  274.         fprintf(f, "\tlabel=%s\n", table.parts[i].bootLabel);
  275.         fprintf(f, "\ttable=/dev/%.3s\n", table.parts[i].device);
  276.         if (strncmp(table.parts[i].device, hdname, 3)) 
  277.             fprintf(f, "\tloader=/boot/any_d.b\n");
  278.       #endif
  279.         }
  280.     }
  281.     }
  282.  
  283.     fclose(f);
  284.  
  285.     winStatus(35, 3, "Running", "Installing boot loader...");
  286.  
  287.     #ifdef __i386__
  288.     rc = runProgramRoot(RUN_LOG, "/mnt", "sbin/lilo", argv);
  289.     #elif __sparc__ 
  290.     rc = doMount("/proc", "/mnt/proc", "proc", 0, 0);
  291.     if (rc) {
  292.         newtPopWindow();
  293.         return rc;
  294.     }
  295.     rc = runProgramRoot(RUN_LOG, "/mnt", "sbin/silo", argv);
  296.     umount("/mnt/proc");
  297.     #else
  298.     #error unsupported architectures
  299.     #endif
  300.  
  301.     newtPopWindow();
  302.  
  303.     if (rc)
  304.     return INST_ERROR;
  305.  
  306.     return 0;
  307. }
  308.  
  309. static int getBootLabels(struct partitionTable table, struct fstab fstab) {
  310.     newtComponent f, okay, text, listbox, label, cancel, edit, answer;
  311.     char buf[80];
  312.     int i, j;
  313.     int foundDos = 0;
  314.     int mustAsk = 0;
  315.     int * map;
  316.     struct partition * curr;
  317.     int * currNum;
  318.     int count;
  319.  
  320.     f = newtForm(NULL, NULL, 0);
  321.     text = newtTextbox(1, 1, 60, 4, NEWT_TEXTBOX_WRAP);
  322.     newtTextboxSetText(text, 
  323.                "The boot manager Red Hat uses can boot other " 
  324.                        "operating systems as well. You need to tell me " 
  325.                        "what partitions you would like to be able to boot " 
  326.                        "and what label you want to use for each of them.");
  327.  
  328.  
  329.     sprintf(buf, "%-10s  %-25s %-18s", "Device", "Partition type", 
  330.             "Boot label");
  331.     label = newtLabel(1, 6, buf);
  332.  
  333.     listbox = newtListbox(1, 7, 7, NEWT_LISTBOX_RETURNEXIT);
  334.     map = alloca(sizeof(int) * table.count);
  335.     
  336.     for (i = 0, count = 0; i < table.count; i++) {
  337.     if (table.parts[i].type != PART_SWAP && 
  338.         table.parts[i].type != PART_IGNORE &&
  339. #ifdef __sparc__
  340.         table.parts[i].type != PART_OTHER &&
  341. #endif
  342.         (table.parts[i].type != PART_DOS || !foundDos)) {
  343.  
  344.         if (table.parts[i].type == PART_DOS) {
  345.         table.parts[i].bootLabel = strdup("dos");
  346.         foundDos = 1;
  347.         }
  348.  
  349.         if (table.parts[i].type == PART_EXT2) {
  350.         for (j = 0; j < fstab.numEntries; j++) {
  351.             if (!strcmp(table.parts[i].device, fstab.entries[j].device))
  352.             break;
  353.         }
  354.  
  355.         if (j < fstab.numEntries && !table.parts[i].bootLabel) 
  356.             continue;
  357.         }
  358.  
  359.         if (!table.parts[i].bootLabel ||
  360.         strcmp(table.parts[i].bootLabel, "linux")) mustAsk = 1;
  361.  
  362.         sprintf(buf, "/dev/%-5s  %-25s %-18s", table.parts[i].device, 
  363.             table.parts[i].tagName, table.parts[i].bootLabel ? 
  364.             table.parts[i].bootLabel : "");
  365.         map[count] = i;
  366.         newtListboxAddEntry(listbox, buf, map + count++);
  367.     } 
  368.     }
  369.  
  370.     newtFormAddComponents(f, text, label, listbox, NULL);
  371.  
  372.     if (!mustAsk) {
  373.     newtFormDestroy(f);
  374.     return 0;
  375.     }
  376.  
  377.     newtOpenWindow(8, 2, 64, 19, "Bootable Partitions");
  378.  
  379.     okay = newtButton(8, 15, "Ok");
  380.     edit = newtButton(26, 15, "Edit");
  381.     cancel = newtButton(44, 15, "Cancel");
  382.  
  383.     newtFormAddComponents(f, okay, edit, cancel, NULL);
  384.  
  385.     do { 
  386.     answer = newtRunForm(f);
  387.     if (answer == edit || answer == listbox) {
  388.         currNum = newtListboxGetCurrent(listbox);
  389.         curr = table.parts + *currNum;
  390.         editBootLabel(curr);
  391.         sprintf(buf, "/dev/%-5s  %-25s %-18s", curr->device, 
  392.             curr->tagName, 
  393.             curr->bootLabel ? curr->bootLabel : "");
  394.  
  395.         newtListboxSetEntry(listbox, currNum - map, buf);
  396.     }
  397.     } while (answer == edit || answer == listbox);
  398.  
  399.     newtFormDestroy(f);
  400.     newtPopWindow();
  401.  
  402.     if (answer == cancel)
  403.     return INST_CANCEL;
  404.     else
  405.     return 0;
  406. }
  407.  
  408. static int getAppendLine(char ** line, int * linear) {
  409.     newtComponent form, text, entry, okay, cancel, answer;
  410.     newtComponent linearCheck;
  411.     char * result = NULL;
  412.     char linearChar = (*linear) ? '*' : ' ';
  413.     int buttonLine = 9;
  414.  
  415.     #ifdef __sparc__
  416.     newtOpenWindow(12, 5, 55, 13, "Silo Installation");
  417.     #else
  418.     /* this is bigger on the Intel to leave room for the linear checkbox */
  419.     newtOpenWindow(12, 5, 55, 15, "Lilo Installation");
  420.     #endif
  421.  
  422.     form = newtForm(NULL, NULL, 0);
  423.     text = newtTextbox(1, 1, 53, 5, NEWT_TEXTBOX_WRAP);
  424.     newtTextboxSetText(text, 
  425.                "A few systems will need to pass special options "
  426.                "to the kernel at boot time for the system to function "
  427.                "properly. If you need to pass boot options to the "
  428.                "kernel, enter them now. If you don't need any or "
  429.                "aren't sure, leave this blank.");
  430.  
  431.     entry = newtEntry(1, 7, *line, 48, &result, 
  432.             NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  433.  
  434.     #ifndef __sparc__
  435.     buttonLine = 11;
  436.     linearCheck = newtCheckbox(1, 9, 
  437.                    "Use linear mode (needed for some SCSI drives)",
  438.                    linearChar, NULL, &linearChar);
  439.     #endif
  440.  
  441.     okay = newtButton(12, buttonLine, "Ok");
  442.     cancel = newtButton(35, buttonLine, "Cancel");
  443.  
  444.     newtFormAddComponents(form, text, entry, NULL);
  445.     #ifndef __sparc__
  446.     newtFormAddComponent(form, linearCheck);
  447.     #endif
  448.     newtFormAddComponents(form, okay, cancel, NULL);
  449.     newtFormSetCurrent(form, okay);
  450.  
  451.     answer = newtRunForm(form);
  452.  
  453.     newtPopWindow();
  454.  
  455.     if (answer == cancel) {
  456.     newtFormDestroy(form);
  457.     return INST_CANCEL;
  458.     }
  459.  
  460.     *linear = linearChar != ' ';
  461.  
  462.     if (!strlen(result)) 
  463.     *line = NULL;
  464.     else 
  465.     *line = strdup(result);
  466.  
  467.     newtFormDestroy(form);
  468.  
  469.     return 0;
  470. }
  471.  
  472. #define LILO_WHERE 2
  473. #define LILO_LABELS 3
  474. #define LILO_INSTALL 4
  475. #define LILO_APPEND 5
  476. #define LILO_DONE 20
  477.     
  478. int installLilo(char * prefix, struct partitionTable table, 
  479.             struct fstab fstab, char * kernelVersion) {
  480.     char * rootDevice, * bootDevice = NULL;
  481.     char * hdName;
  482.     char * where;
  483.     char * append = NULL;
  484.     char * chptr = NULL;
  485.     int i;
  486.     int rc;
  487.     int stage = LILO_WHERE;
  488.     static int linear = 0;
  489.  
  490.     hdName = alloca(4);
  491.     strncpy(hdName, table.parts[0].device, 3);
  492.     hdName[3] = '\0';
  493.     
  494.     for (i = 0; i < fstab.numEntries; i++) {
  495.     if (!strcmp(fstab.entries[i].mntpoint, "/boot")) break;
  496.     }
  497.  
  498.     if (i < fstab.numEntries) 
  499.     bootDevice = fstab.entries[i].device;
  500.  
  501.     for (i = 0; i < fstab.numEntries; i++) {
  502.     if (!strcmp(fstab.entries[i].mntpoint, "/")) break;
  503.     }
  504.  
  505.     rootDevice = fstab.entries[i].device;
  506.     if (!bootDevice) {
  507.     bootDevice = rootDevice;
  508.     }
  509.  
  510.     for (i = 0; i < table.count; i++) {
  511.     if (!strcmp(table.parts[i].device, bootDevice)) {
  512.         table.parts[i].bootLabel = strdup("linux");
  513.         break;
  514.     }
  515.     }
  516.  
  517.     while (stage != LILO_DONE) {
  518.     switch (stage) {
  519.       case LILO_WHERE:
  520.         rc = liloWhere(hdName, bootDevice, &where);
  521.             if (rc == SKIP_LILO ) return 0;
  522.         if (rc) return rc;
  523.         stage = LILO_APPEND;
  524.         break;
  525.  
  526.       case LILO_APPEND:
  527.         chptr = append;
  528.         rc = getAppendLine(&chptr, &linear);
  529.  
  530.         if (rc == INST_ERROR) return INST_ERROR;
  531.         if (rc == INST_CANCEL)
  532.         stage = LILO_WHERE;
  533.         else {
  534.         stage = LILO_LABELS;
  535.  
  536.         if (append) free(append);
  537.         if (chptr) {
  538.             append = alloca(strlen(chptr) + 1);
  539.             strcpy(append, chptr);
  540.             free(chptr);
  541.         } else {
  542.             append = NULL;
  543.         }
  544.         }
  545.  
  546.         break;
  547.  
  548.       case LILO_LABELS:
  549.         rc = getBootLabels(table, fstab);
  550.         if (rc == INST_ERROR) return INST_ERROR;
  551.         if (rc == INST_CANCEL)
  552.         stage = LILO_APPEND;
  553.         else
  554.         stage = LILO_INSTALL;
  555.         break;
  556.  
  557.       case LILO_INSTALL:
  558.         rc = doinstallLilo(prefix, where, rootDevice, table, append, 
  559.                 kernelVersion, hdName, linear);
  560.         if (rc == INST_ERROR) return INST_ERROR;
  561.         stage = LILO_DONE;
  562.         break;
  563.     }
  564.     }
  565.  
  566.     return 0;
  567. }
  568.